package com.css.fxfzcpxx.modules.questionData.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.css.fxfzcpxx.base.response.RestResponse;
import com.css.fxfzcpxx.base.user.service.UserService;
import com.css.fxfzcpxx.base.user.viewobjects.UserBaseInfoVO;
import com.css.fxfzcpxx.constants.YNEnum;
import com.css.fxfzcpxx.modules.certificateManage.entity.CertificateRule;
import com.css.fxfzcpxx.modules.certificateManage.entity.UserCertificate;
import com.css.fxfzcpxx.modules.certificateManage.repository.CertificateManageRepository;
import com.css.fxfzcpxx.modules.certificateManage.service.CertificateManageService;
import com.css.fxfzcpxx.modules.certificateManage.vo.CertificateRuleVo;
import com.css.fxfzcpxx.modules.courseManage.entity.CourseManage;
import com.css.fxfzcpxx.modules.courseManage.entity.TestPaperTemplateRule;
import com.css.fxfzcpxx.modules.courseManage.repository.CourseManageRepository;
import com.css.fxfzcpxx.modules.questionData.entity.QuestionData;
import com.css.fxfzcpxx.modules.questionData.entity.UserTestHistory;
import com.css.fxfzcpxx.modules.questionData.entity.UserTsetQuestion;
import com.css.fxfzcpxx.modules.questionData.param.GetScore;
import com.css.fxfzcpxx.modules.questionData.param.GetScoreParam;
import com.css.fxfzcpxx.modules.questionData.param.QuestionDataParam;
import com.css.fxfzcpxx.modules.questionData.repository.QuestionDataRepository;
import com.css.fxfzcpxx.modules.questionData.service.QuestionDataService;
import com.css.fxfzcpxx.modules.questionData.vo.*;
import com.css.fxfzcpxx.modules.typeManage.entity.TypeManage;
import com.css.fxfzcpxx.modules.typeManage.service.TypeManageService;
import com.css.fxfzcpxx.util.CreateGson;
import com.css.fxfzcpxx.util.EasyPoiExcelUtil;
import com.css.fxfzcpxx.util.PlatformDateUtils;
import com.css.fxfzcpxx.web.PlatformSessionContext;
import com.css.fxfzcpxx.zcpt.sys.entity.SUser;
import com.css.fxfzcpxx.zcpt.sys.service.impl.SUserServiceImpl;
import com.google.common.collect.Lists;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @Author: zhangSongRui
 * @CreateTime: 2023/03/11
 * @Description: 题库管理
 */
@Service
public class QuestionDataServiceImpl implements QuestionDataService {

    @Resource
    private QuestionDataRepository questionDataRepository;
    @Resource
    private TypeManageService typeManageService;
    @Resource
    private CourseManageRepository courseManageRepository;
    @Resource
    private CertificateManageRepository certificateManageRepository;
    @Resource
    private CertificateManageService certificateManageService;
    @Resource
    SUserServiceImpl sUserServiceImpl;

    @Resource
    UserService userService;

    @Override
    public Map<String, Object> getPage(int curPage, int pageSize, QuestionDataParam param) {
        return questionDataRepository.getPage(curPage, pageSize, param);
    }

    @Override
    public RestResponse updateById(QuestionData param) {
        List<String> list = new ArrayList<>();
        list.add(param.getQuestionName());
        param.setUpdateUser(PlatformSessionContext.getUserID());
        param.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
        questionDataRepository.updateById(param);
        return RestResponse.succeed("修改成功");
    }

    @Override
    public void delete(String ids) {
        questionDataRepository.delete(Arrays.asList(ids.split(",")));
    }

    @Override
    public JSONObject findById(String id) {
        QuestionData byId = questionDataRepository.findById(id);
        Map<String, Object> obj = new HashMap<>();
        Map<String, String> map = new HashMap<>();
        map.put("A",byId.getA());
        map.put("B",byId.getB());
        map.put("C",byId.getC());
        map.put("D",byId.getD());
        map.put("E",byId.getE());
        map.put("F",byId.getF());
        obj.put("id",byId.getId());
        obj.put("typeId",byId.getTypeId());
        obj.put("typeName",byId.getTypeName());
        obj.put("questionType",byId.getQuestionType());
        obj.put("questionName",byId.getQuestionName());
        obj.put("optionObj",map);
        obj.put("answers",byId.getAnswers());
        obj.put("analysis",byId.getAnalysis());
        String s = JSONObject.toJSONString(obj);
        JSONObject jsonObject = JSONObject.parseObject(s);
        return jsonObject;
    }

    @Override
    public RestResponse save(QuestionData param) {
        List<String> list = new ArrayList<>();
        list.add(param.getQuestionName());
        //校验重复
        if (testCheck(list)){
            return RestResponse.fail("题目名称重复");
        }
        param.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        param.setCreateUser(PlatformSessionContext.getUserID());
        param.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
        param.setDelFlag(YNEnum.N.toString());
        questionDataRepository.save(param);
        return RestResponse.succeed("新增成功");
    }

    @Override
    public void exportData(HttpServletResponse response, String ids) {
        List<QuestionData> list = questionDataRepository.queryByIds(Arrays.asList(ids.split(",")));
        EasyPoiExcelUtil.exportExcel(list, "题库目录", "sheet1", QuestionData.class, "题库目录", response);
    }

    @Override
    public String reportImport(InputStream inputStream) {
        try {
            Workbook workbook = WorkbookFactory.create(inputStream);
            Map<String, Object> map = getList(workbook);
            //获取校验结果
            if (!String.valueOf(map.get("message")).equals("正常")) {
                return String.valueOf(map.get("messageInfo"));
            }
            //校验是否有重复题目
            List<QuestionData> list= (List<QuestionData>) map.get("list");
            //导入的所有标题名
            ArrayList<String> titleName = new ArrayList<>();
            for (QuestionData questionData : list) {
                titleName.add(questionData.getQuestionName());
            }
            //三十个一校验
            List<List<String>> partition = Lists.partition(titleName, 30);
            for (List<String> strings : partition) {
                if (testCheck(strings)){
                    StringBuilder msg =new StringBuilder("以下题目中有重复试题请检查");
                    for (String string : strings) {
                        msg.append(string).append("   ");
                    }
                    return msg.toString();
                }
            }
            questionDataRepository.batchSave((List<QuestionData>) map.get("list"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "导入成功";
    }

    //根据规则获取试卷
    @Override
    public RestResponse getTestById(String id) {
        //查询该课堂的规则
        CourseManage byId = courseManageRepository.findById(id);
        if (byId.getExercise().equals("1")) {
            return RestResponse.fail("该课堂没有试题");
        }
        //获取规则
        List<TestPaperTemplateRule> templateRuleById = courseManageRepository.findTemplateRuleById(byId.getExerciseId());
        //单选
        ArrayList<QuestionDataVO> singleChoice = new ArrayList<>();
        //多选
        ArrayList<QuestionDataVO> multipleSelection = new ArrayList<>();
        //判断
        ArrayList<QuestionDataVO> judgment = new ArrayList<>();
        for (TestPaperTemplateRule testPaperTemplateRule : templateRuleById) {
            //如果单选题不为null并且数量不为0
            if (!StringUtils.isEmpty(testPaperTemplateRule.getSingleOption()) & !testPaperTemplateRule.getSingleOption().equals("0")) {
                randomTest("0", testPaperTemplateRule.getTypeId(), Integer.parseInt(testPaperTemplateRule.getSingleOption()), testPaperTemplateRule.getSingleOptionScore(), singleChoice);
            }
            //如果多选题不为null并且数量不为0
            if (!StringUtils.isEmpty(testPaperTemplateRule.getMultipleSelection()) & !testPaperTemplateRule.getMultipleSelection().equals("0")) {
                randomTest("1", testPaperTemplateRule.getTypeId(), Integer.parseInt(testPaperTemplateRule.getMultipleSelection()), testPaperTemplateRule.getMultipleSelectionScore(), multipleSelection);
            }
            //如果判断不为null并且数量不为0
            if (!StringUtils.isEmpty(testPaperTemplateRule.getJudgment()) & !testPaperTemplateRule.getJudgment().equals("0")) {
                randomTest("2", testPaperTemplateRule.getTypeId(), Integer.parseInt(testPaperTemplateRule.getJudgment()), testPaperTemplateRule.getJudgmentScore(), judgment);
            }
        }
        TestVO testVO = new TestVO();
        //写入单选
        testVO.setSingleChoice(singleChoice);
        //写入多选
        testVO.setMultipleSelection(multipleSelection);
        //写入判断
        testVO.setJudgment(judgment);
        return RestResponse.succeed(testVO);
    }

    //判分并将试卷保存到历史试卷中
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResponse getScore(GetScoreParam getScoreParam) {
        List<GetScore> list = getScoreParam.getList();
        //得分
        Integer Score = 0;
        //总分
        Integer TotalScore = 0;
        UserTestHistory userTestHistory = new UserTestHistory();
        userTestHistory.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        List<UserTsetQuestion> userTQList = new ArrayList<>();
        //循环判分
        for (int i = 0; i < list.size(); i++) {
            GetScore getScore = list.get(i);
            UserTsetQuestion userTsetQuestion = new UserTsetQuestion();
            userTsetQuestion.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            //考试id
            userTsetQuestion.setTestId(userTestHistory.getId());
            //习题id
            userTsetQuestion.setQuestionId(getScore.getId());
            //顺序
            userTsetQuestion.setSequence(i);
            userTsetQuestion.setUserAnswer(getScore.getUserAnswer());
            //单选
            if (getScore.getQuestionType().equals("0")) {
                if (getScore.getAnswers().equals(getScore.getUserAnswer())) {
                    Score += Integer.parseInt(getScore.getQueryScore());
                    userTsetQuestion.setCorrect("0");
                }else {
                    userTsetQuestion.setCorrect("1");
                }
                TotalScore += Integer.parseInt(getScore.getQueryScore());
                userTQList.add(userTsetQuestion);
                continue;
            }
            //判断
            if (getScore.getQuestionType().equals("2")) {
                if (getScore.getAnswers().equals(getScore.getUserAnswer())) {
                    Score += Integer.parseInt(getScore.getQueryScore());
                    userTsetQuestion.setCorrect("0");
                }else {
                    userTsetQuestion.setCorrect("1");
                }
                TotalScore += Integer.parseInt(getScore.getQueryScore());
                userTQList.add(userTsetQuestion);
                continue;
            }
            //多选
            if (getScore.getQuestionType().equals("1")) {
                String[] split = getScore.getUserAnswer().split(",");
                //获取正确答案长度
                String trim =  getScore.getAnswers().trim();
                String[] answerSplit = trim.split(",");
                int m = 0;
                //如果答案数量对不上则为错
                if (split.length!=answerSplit.length){
                    m = 1;
                }
                //如果答案不包含
                for (String s : split) {
                    if (!getScore.getAnswers().contains(s)) {
                        m = 1;
                    }
                }
                if (m == 0) {
                    Score += Integer.parseInt(getScore.getQueryScore());
                    userTsetQuestion.setCorrect("0");
                }else {
                    userTsetQuestion.setCorrect("1");
                }
                TotalScore += Integer.parseInt(getScore.getQueryScore());
                userTQList.add(userTsetQuestion);
                continue;
            }
        }
        //生成用户历史考试数据
        //获取用户名称
        String sUser = sUserServiceImpl.getSUser(PlatformSessionContext.getUserID());
        SUser userInfo = CreateGson.createGson().fromJson(sUser, SUser.class);
        String userName="";
        if(userInfo==null){
            UserBaseInfoVO user = userService.getUser(PlatformSessionContext.getUserID());
            userName=user.getUserName();
        }else{
            userName=userInfo.getUserName();
        }


        userTestHistory.setCourseId(getScoreParam.getCourseId());
        userTestHistory.setTotalScore(TotalScore);
        userTestHistory.setScore(Score);
        userTestHistory.setDelFlag(YNEnum.N.toString());
        userTestHistory.setCreateUser(PlatformSessionContext.getUserID());
        //写入用户名称
        userTestHistory.setCreateName(userName);
        userTestHistory.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
        questionDataRepository.saveUserTestHistory(userTestHistory);
        //保存用户历史考试题
        questionDataRepository.batchSaveUserTestQuestion(userTQList);
        //生成证书
        //获取证书规则
        List<CertificateRuleVo> certificateList = certificateManageRepository.queryRule();
        //获取分数百分比
        BigDecimal b = new BigDecimal((float)Score/TotalScore);
        Double aDouble = b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue()*100;
        UserCertificate userCertificate = new UserCertificate();
        ScoreVO scoreVO = new ScoreVO();
        //优秀证书
        if (aDouble>=Double.parseDouble(certificateList.get(0).getGreaterThan())){
            String id = certificateManageService.getCertificateId(certificateList.get(0).getCertificateId(),PlatformSessionContext.getUserID());
            //uuid
            userCertificate.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            //课堂id
            userCertificate.setCourseId(getScoreParam.getCourseId());
            //考试id
            userCertificate.setTestId(userTestHistory.getId());
            //模板id
            userCertificate.setTemplateId(certificateList.get(0).getCertificateId());
            //证书id
            userCertificate.setCertificateId(id);
            //创建人
            userCertificate.setCreateUser(PlatformSessionContext.getUserID());
            //创建时间
            userCertificate.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
            certificateManageRepository.saveUserCertificate(userCertificate);
            scoreVO.setCertificateId(id);
        }
        //合格证书
        else if (aDouble>=Double.parseDouble(certificateList.get(1).getGreaterThan())){
            String id = certificateManageService.getCertificateId(certificateList.get(1).getCertificateId(),PlatformSessionContext.getUserID());
            //uuid
            userCertificate.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            //课堂id
            userCertificate.setCourseId(getScoreParam.getCourseId());
            //考试id
            userCertificate.setTestId(userTestHistory.getId());
            //模板id
            userCertificate.setTemplateId(certificateList.get(1).getCertificateId());
            //证书id
            userCertificate.setCertificateId(id);
            //创建人
            userCertificate.setCreateUser(PlatformSessionContext.getUserID());
            //创建时间
            userCertificate.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
            certificateManageRepository.saveUserCertificate(userCertificate);
            scoreVO.setCertificateId(id);
        }
        scoreVO.setScore(String.valueOf(Score));
        scoreVO.setTestId(userTestHistory.getId());
        scoreVO.setTime(PlatformDateUtils.getCurrentTimestamp());
        //获取历史最高分
        UserTestHistory maximumScore =questionDataRepository.getMaximumScore(getScoreParam.getCourseId(),PlatformSessionContext.getUserID());
        scoreVO.setMaximumScore(String.valueOf(maximumScore.getScore()));
        return RestResponse.succeed(scoreVO);
    }

    /**
     * 试题校验如果有一样的则不能导入
     *
     * @param titleName 标题名称
     */
    private Boolean testCheck(List<String> titleName) {
        //查询标题相同的数量
        Integer num = questionDataRepository.testCheck(titleName);
        if (num!=0){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 随机试题
     *
     * @param type   题目类型(0单选1多选2判断)
     * @param typeId 类别id
     * @param r      要随机几道题
     * @param Score  这种类型的题几分
     * @param test   将题库中的题随机放入
     */
    private void randomTest(String type, String typeId, int r, String Score, List<QuestionDataVO> test) {
        //根据题目类型和类别id查询出来的题库
        List<QuestionData> singleChoiceList = questionDataRepository.queryQuestionByTypeId(typeId, type);
        //如果题库的题不是0并且题库中的题大于或等于你要随机的题的数量
        if (singleChoiceList.size() != 0 & (r <= singleChoiceList.size())) {
            //循环次数
            int num = r;
            for (int i = 0; i < num; i++) {
                //随机一个0到size的数;
                int j = (int) (Math.random() * (singleChoiceList.size()));
                QuestionDataVO questionDataVO = new QuestionDataVO();
                //复制
                BeanUtils.copyProperties(singleChoiceList.get(j), questionDataVO);
                //写入分数
                questionDataVO.setQueryScore(Score);
                //写入
                test.add(questionDataVO);
                //删除写入的那道题
                singleChoiceList.remove(j);
            }
        }
    }

    //获取list
    private Map<String, Object> getList(Workbook workbook) {
        String userID = PlatformSessionContext.getUserID();
        Map<String, Object> map = new HashMap<>();
        //构筑物部分
        List<QuestionData> list = new ArrayList<>();
        if (workbook != null) {
            //循环除了第一行的所有行
            /** 得到第一个sheet */
            Sheet sheet = workbook.getSheetAt(0);
            /** 得到Excel的行数 */
            int totalRows = sheet.getPhysicalNumberOfRows();
            HSSFDataFormatter hSSFDataFormatter = new HSSFDataFormatter();
            /** 循环Excel的行 从第七行开始*/
            map.put("message", "正常");
            for (int r = 1; r < totalRows; r++) {
                Row row = sheet.getRow(r);
                if (row == null) {
                    continue;
                }
                QuestionData obj = new QuestionData();
                //流水号
                String num = hSSFDataFormatter.formatCellValue(row.getCell(0));
                if (StringUtils.isEmpty(num)) {
                    break;
                }
                //主键id
                obj.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                if (StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(1)))) {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + "题目不能为空");
                    break;
                }
                if (StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(2)))) {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + "题型不能为空");
                    break;
                }
                if (StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(3)))) {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + "选项A不能为空");
                    break;
                }
                if (StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(4)))) {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + "选项B不能为空");
                    break;
                }
                if (StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(9)))) {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + "正确答案不能为空");
                    break;
                }
                if (StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(11)))) {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + "分类不能为空");
                    break;
                }
                //题目
                obj.setQuestionName(hSSFDataFormatter.formatCellValue(row.getCell(1)).trim());
                //题目类型(0单选1多选2判断)
                if (hSSFDataFormatter.formatCellValue(row.getCell(2)).equals("单选")) {
                    obj.setQuestionType("0");
                } else if (hSSFDataFormatter.formatCellValue(row.getCell(2)).equals("多选")) {
                    obj.setQuestionType("1");
                } else if (hSSFDataFormatter.formatCellValue(row.getCell(2)).equals("判断")) {
                    obj.setQuestionType("2");
                } else {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + ",题型只能填单选题,多选题,与判断题");
                    break;
                }
                //选项A
                obj.setA(hSSFDataFormatter.formatCellValue(row.getCell(3)).trim());
                //选项B
                obj.setB(hSSFDataFormatter.formatCellValue(row.getCell(4)).trim());
                //选项C
                if (!StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(5)).trim())) {
                    obj.setC(hSSFDataFormatter.formatCellValue(row.getCell(5)).trim());
                }
                //选项D
                if (!StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(6)).trim())) {
                    obj.setD(hSSFDataFormatter.formatCellValue(row.getCell(6)).trim());
                }
                //选项E
                if (!StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(7)).trim())) {
                    obj.setE(hSSFDataFormatter.formatCellValue(row.getCell(7)).trim());
                }
                //选项F
                if (!StringUtils.isEmpty(hSSFDataFormatter.formatCellValue(row.getCell(8)).trim())) {
                    obj.setF(hSSFDataFormatter.formatCellValue(row.getCell(8)).trim());
                }
                //ABCDEF最多6个如果判断题则只有AB选项
                if (!Pattern.matches("^[A-F]+$", hSSFDataFormatter.formatCellValue(row.getCell(9)).trim())) {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + ",答案只能是大写字母A到F");
                    break;
                }
                if (obj.getQuestionType().equals("2")) {
                    if (!Pattern.matches("^[A-B]+$", hSSFDataFormatter.formatCellValue(row.getCell(9)).trim())) {
                        map.put("message", "格式错误");
                        map.put("messageInfo", "序号" + num + ",判断题答案只能是A或者B");
                        break;
                    }
                }
                String trim = hSSFDataFormatter.formatCellValue(row.getCell(9));
                String answer = trim.replaceAll("[A-Z]", " $0").trim();
                String answer1=answer.replaceAll("\\s",",");
                obj.setAnswers(answer1);
                //解析
                obj.setAnalysis(hSSFDataFormatter.formatCellValue(row.getCell(10)).trim());
                //分类
                TypeManage typeManage = typeManageService.queryIdByName(hSSFDataFormatter.formatCellValue(row.getCell(11)).trim());
                if (null == typeManage) {
                    map.put("message", "格式错误");
                    map.put("messageInfo", "序号" + num + ",没有该分类");
                    break;
                }
                obj.setTypeId(typeManage.getId());
                //0正常1删除
                obj.setDelFlag(YNEnum.N.toString());
                //创建人
                obj.setCreateUser(userID);
                //创建时间
                obj.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
                list.add(obj);
            }
            if (!map.get("message").equals("正常")) {
                return map;
            }
        }
        map.put("list", list);
        return map;
    }
}
